// SPDX-License-Identifier: GPL-2.0 or GPL-3.0
// Copyright © 2018-2019 Ariadne Devos
/* sHT -- in case of a bug, crash graceful */

#ifndef _sHT_BUGS_H
#define _sHT_BUGS_H

#include <stddef.h>
#include <sys/types.h>
#include <limits.h>

#include <sHT/compiler.h>

/** Bug catching

  This is for detecting bugs of the class that cause memory corruption,
  where trying to continue only amplifies it. It is also for bugs that
  cause a smoke test to fail, in which case the application isn't useful
  at all until the bug isn't fixed.

  The functions are: @var{sHT_halt}, @var{sHT_assert}, @var{sHT_require}
  and @var{sHT_todo}. The last one is intentionally left undocumented,
  for a obvious reason here documented: it should not be needed outside
  proof-of-concepts. */

/** Check that a precondition is true.

  This is only for catching bugs. In particular, it may speculatively
  be ignored. */
#define sHT_require(b) \
  do { \
    if (sHT_unlikely(!(b))) \
      sHT_halt(#b); \
  } while (0)

/** Check that an invariant is true.

  This is only for catching bugs. In particular, it may speculatively
  be ignored. */
#define sHT_assert(b) sHT_require(b)

/* Last entry has .code == 0, and is the default */
struct sHT_bug_option {
	const char *msg;
	int code;
};

__attribute__((cold)) __attribute__((nonnull (1)))
_Noreturn void
sHT_bug(const struct sHT_bug_option *options, int code);

#define sHT_todo(b) do { if ((b)) __builtin_trap(); } while (0)

#endif
